package com.flyqiu.form.extensions;


import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.flyqiu.common.clazz.FlyQiuClassTools;
import com.flyqiu.common.sc.FlyQiyDefaultSCManage;
import com.flyqiu.common.sc.FlyQiySCManage;
import com.flyqiu.common.tools.FlyQiuCollectionTools;
import com.flyqiu.form.api.tools.FlyQiuAvueColTools;
import com.flyqiu.form.api.tools.FlyQiuTableOptionTools;
import com.flyqiu.form.extensions.convert.FlyQiuAvueMapperConfig;
import com.flyqiu.form.extensions.convert.mapping.AvueDefaultMapper;
import com.flyqiu.form.extensions.convert.mapping.FlyQiuAvueMapper;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j

public class FlyQiuFormDataConvert {
    @Getter
    private Map<String, Object> headers;
    @Getter
    private String homeUrl;
    @Getter
    private Map<String, Class<? extends FlyQiuAvueMapper>> mapperClassMap;
    @Getter
    private Class<? extends FlyQiuAvueMapper> globalDefaultMapper;
    @Getter
    private FlyQiySCManage flyQiySCManage;


    private List<FlyQiuAvueMapper> mappers;

    private FlyQiuFormDataConvert() {

    }

    public static FlyQiuFormDataConvert create(FlyQiySCManage flyQiySCManage) {
        return create(flyQiySCManage, null, null);
    }

    public static FlyQiuFormDataConvert clone(FlyQiuFormDataConvert convert) {
        return create(convert.flyQiySCManage, convert.getHomeUrl(), convert.getHeaders(), convert.getMapperClassMap(), convert.getGlobalDefaultMapper());
    }

    public static FlyQiuFormDataConvert create(FlyQiySCManage flyQiySCManage, String homeUrl, Map<String, Object> headers) {
        return create(flyQiySCManage, homeUrl, headers, null);
    }

    public static FlyQiuFormDataConvert create(FlyQiySCManage flyQiySCManage, String homeUrl,
                                               Map<String, Object> headers,
                                               Map<String, Class<? extends FlyQiuAvueMapper>> mappers) {
        return create(flyQiySCManage, homeUrl, headers, mappers, null);
    }

    public static FlyQiuFormDataConvert create(FlyQiySCManage flyQiySCManage, String homeUrl,
                                               Map<String, Object> headers,
                                               Map<String, Class<? extends FlyQiuAvueMapper>> mappers,
                                               Class<? extends FlyQiuAvueMapper> globalDefaultMapper) {
        FlyQiuFormDataConvert convert = new FlyQiuFormDataConvert();
        if (mappers == null || mappers.isEmpty()) {
            mappers = FlyQiuAvueMapperConfig.getInstance().getConfigMapper();
        }
        if (flyQiySCManage == null) {
            flyQiySCManage = FlyQiyDefaultSCManage.getInstance();
        }
        convert.flyQiySCManage = flyQiySCManage;
        convert.homeUrl = homeUrl;
        convert.headers = headers;
        if (globalDefaultMapper == null) {
            globalDefaultMapper = AvueDefaultMapper.class;
        }
        convert.globalDefaultMapper = globalDefaultMapper;
        convert.mapperClassMap = mappers;
        return convert;
    }

    public void init(JSONObject formOption) {
        JSONArray column = FlyQiuTableOptionTools.getColumns(formOption);
        mappers = new ArrayList<>();
        for (int i = column.size() - 1; i >= 0; i--) {
            JSONObject col = column.getJSONObject(i);
            FlyQiuAvueMapper avueColMapper = getAvueColMapper(col);
            avueColMapper.init(this, col);
            mappers.add(avueColMapper);
        }

    }

    public Map<String, FlyQiuAvueMapper> getPropMapperMap() {
        if (mappers == null) {
            throw new IllegalArgumentException("请先调用init方法");
        }
        return mappers.stream().collect(Collectors.toMap(FlyQiuAvueMapper::getProp, e -> e));
    }


    public FlyQiuAvueMapper getAvueColMapper(JSONObject col) {
        String columnComponentName = FlyQiuAvueColTools.getColumnComponentName(col);
        Class<? extends FlyQiuAvueMapper> mapperClazz = mapperClassMap.getOrDefault(columnComponentName, globalDefaultMapper);
        return FlyQiuClassTools.createObject(mapperClazz);
    }


    private List<JSONObject> convertDataToLabel(List<JSONObject> dataList) {
        if (mappers == null) {
            throw new IllegalArgumentException("请先调用init方法");
        }
        List<JSONObject> result = new ArrayList<>();
        FlyQiuCollectionTools.iteratorIndex(dataList, (jsonObject, index) -> {
            jsonObject = convertDataToLabel(jsonObject);
            result.add(jsonObject);
        });

        return result;
    }

    public JSONArray convertDataToLabel(JSONArray dataSource) {
        if (mappers == null) {
            throw new IllegalArgumentException("请先调用init方法");
        }
        JSONArray result = new JSONArray();
        for (int i = 0; i < dataSource.size(); i++) {
            JSONObject jsonObject = convertDataToLabel(dataSource.getJSONObject(i));
            result.add(jsonObject);
        }
        return result;
    }

    public JSONArray convertDataToLabel(Collection<? extends JSONObject> dataSource) {
        JSONArray result = new JSONArray();
        Iterator<? extends JSONObject> iterator = dataSource.iterator();
        int i = 0;
        while (iterator.hasNext()) {
            JSONObject dataItem = iterator.next();
            JSONObject item = convertDataToLabel(dataItem);
            item.put("_start_index", i + 1);
            result.add(item);
            i += 0;
        }
        return result;
    }


    public JSONObject convertDataToLabel(JSONObject data) {
        JSONObject result = new JSONObject();
        String prop;
        JSONObject colOption;
        FlyQiuAvueMapper mapper;
        for (int i = mappers.size() - 1; i > -1; i--) {
            mapper = mappers.get(i);

            colOption = mapper.getColumnOption();
            prop = colOption.getString("prop");
            if (StringUtils.isBlank(prop)) {
                continue;
            }

            Object val = data.get(prop);
            if (colOption.containsKey("ignoreConvert") && colOption.getBoolean("ignoreConvert")) {
                result.put(prop, val);
                continue;
            }
            if (val == null) {
                result.put(prop, "");
                continue;
            }
            Object value = mapper.valueToLabel(val);
            result.put(prop, value);
        }
        return result;
    }
}
